﻿/*
 * Copyright (c) 2020-2025, Qingdao Digital Intelligent Ship & Ocean Technology Co., Ltd.
 * All rights reserved.
 *
 * This file is part of FastCAE and is distributed under the terms of the
 * BSD 3-Clause License. See the LICENSE file in the project root for details.
 */

#include "Solid.h"
// core
#include "FITK_Kernel/FITKCore/FITKDataRepo.h"
#include "FITK_Kernel/FITKCore/FITKOperatorRepo.h"
//framework
#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"
//python
#include "FITK_Kernel/FITKPython/FITKPythonInterface.h"
//operator
#include "OperatorsInterface/GraphEventOperator.h"
#include "FITK_Kernel/FITKCore/FITKActionOperator.h"

//interface
#include "FITK_Interface/FITKInterfaceGeometry/FITKGeoCommandList.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKGeoInterfaceFactory.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoModelBox.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoModelSphere.h"
//component
#include "FITK_Component/FITKGeoCompOCC/FITKOCCModelSolid.h"
#include "FITK_Component/FITKGeoCompOCC/FITKOCCModelOperSolid.h"
#include <QMetaEnum>
#include <QDebug>

Solid::Solid(int id /*= 0*/)
{
    if (id == 0) return;
    m_command = FITKDATAREPO->getTDataByID<Interface::FITKAbsGeoModelSolid>(id);
}

Solid::Solid(Interface::FITKAbsGeoCommand* command)
{
    m_command = command;
}

Solid::~Solid()
{
    if (!m_command)
    {
        delete m_command;
        m_command = nullptr;
    }
}

bool Solid::boxParameterInit(Interface::FITKAbsGeoCommand * command, int modelingType, QList<double> arg1, QList<double> arg2)
{
    auto commandBox = dynamic_cast<Interface::FITKAbsGeoModelBox*>(command);
    if (!commandBox) return false;
    double point[3]{ arg1[0],arg1[1],arg1[2] }, length[3]{ arg2[0],arg2[1],arg2[2] };
    //长宽高创建 参数
    commandBox->setPoint1(point);
    commandBox->setLength(length);
    //两点创建 参数
    if (modelingType != 1)
    {
        double len[3] = { std::abs(arg1[0] - arg2[0]), std::abs(arg1[1] - arg2[1]), std::abs(arg1[2] - arg2[2]) };
        commandBox->setLength(len);
    }
    m_command = command;
    return true;
}

bool Solid::sphereParameterInit(Interface::FITKAbsGeoCommand* command, QList<double> arg1, double Radius)
{
    auto commandSphere = dynamic_cast<Interface::FITKAbsGeoModelSphere*>(command);
    if (!commandSphere) return false;
    double point[3]{ arg1[0],arg1[1],arg1[2] };
    commandSphere->setLocation(point);
    commandSphere->setRadius(Radius);
    m_command = command;
    return true;
}

bool Solid::chamferParameterInit(Interface::FITKAbsGeoCommand* command, int opCommandID, QList<int> opIndexs, double length)
{
    auto commandChamfer = dynamic_cast<Interface::FITKAbsGeoModelChamferSolid*>(command);
    if (!commandChamfer) return false;

    commandChamfer->setInputCmdId(opCommandID);
    // commandChamfer->setEdgeIndice(opIndexs);
    commandChamfer->setDistance(length);
    m_command = command;
    return true;
}

QString Solid::getName()
{
    if (m_command) return m_command->getDataObjectName();
    return QString();
}

Solid* SolidWapper::static_Solid_CreateBox(QString opName, int modelingType, QList<double> arg1, QList<double> arg2)
{
    auto command = wTools.getGeoCommand("FGTBox");
    Solid* solid = new Solid();
    // 获取全局变量
    auto geoCmdList = FITKGLODATA->getGeometryData<Interface::FITKGeoCommandList>();

    if (command && solid->boxParameterInit(command, modelingType, arg1, arg2) && command->update())
    {
        geoCmdList->appendDataObj(command);
        command->setDataObjectName(geoCmdList->checkName(QString("Box-%1").arg(geoCmdList->getDataCount() + 1)));
        wTools.updateExecutionStatus(true);
        updateUI(-1);
        return solid;
    }
    wTools.updateExecutionStatus(false);
    delete solid;
    return nullptr;
}

Solid* SolidWapper::static_Solid_CreateSphere(QString opName, QList<double> arg1, double radius)
{
    auto command = wTools.getGeoCommand("FGTSphere");
    Solid* solid = new Solid(command);
    // 获取全局变量
    auto geoCmdList = FITKGLODATA->getGeometryData<Interface::FITKGeoCommandList>();

    if (command && solid->sphereParameterInit(command, arg1, radius) && command->update())
    {
        geoCmdList->appendDataObj(command);
        command->setDataObjectName(geoCmdList->checkName(QString("Sphere-%1").arg(geoCmdList->getDataCount() + 1)));
        wTools.updateExecutionStatus(true);
        updateUI(-1);
        return solid;
    }
    wTools.updateExecutionStatus(false);
    delete solid;
    return nullptr;
}

void SolidWapper::delete_Solid(Solid* s)
{
    if (s) delete s;
}

QString SolidWapper::getName(Solid* s)
{
    if (s) return s->getName();
    return QString();
}

void SolidWapper::static_Solid_CreateChamfer(QString editName, QString opName, QList<int> indexs, double length)
{
    // 获取全局变量
    auto geoCmdList = FITKGLODATA->getGeometryData<Interface::FITKGeoCommandList>();
    bool errorStatus = false;
    auto opSolid = geoCmdList->getDataByName(opName);
    auto operKey = editName.isEmpty() ? QString("action%1Create") : QString("action%1Edit");
    Interface::FITKAbsGeoCommand* command = editName.isEmpty() ? wTools.getGeoCommand("FGTChamferSolid") : geoCmdList->getDataByName(editName);
    Solid* solid = new Solid(command);

    if (opSolid && command)
    {
        QString geoTypeName = QMetaEnum::fromType<Interface::FITKGeoEnum::FITKGeometryComType>().valueToKey(command->getGeometryCommandType());
        if (geoTypeName.isEmpty()) return;

        Core::FITKActionOperator* operGeo = FITKOPERREPO->getOperatorT<Core::FITKActionOperator>(operKey.arg(geoTypeName.mid(3)));
        auto sManager = opSolid->getShapeAgent()->getVirtualTopoManager()->getShapeVirtualTopoManager(Interface::FITKGeoEnum::VTopoShapeType::VSEdge);
        QList<int> oIndexs;
        for (int i = 0; i < indexs.size(); i++)
        {
            auto edgeData = sManager->getDataByIndex(indexs[i]);
            if (!edgeData) continue;
            oIndexs.append(edgeData->getDataObjectID());
        }

        // 清空参数并重新传递输入参数。
        operGeo->clearArgs();
        operGeo->setArgs("InputCmdID", opSolid->getDataObjectID());
        operGeo->setArgs("InputEdgeIDs", QVariant::fromValue(oIndexs));
        operGeo->setArgs("InputDistance", length);
        bool isEp = operGeo->execProfession();
        wTools.updateExecutionStatus(isEp);

        if (!isEp) delete solid, solid = nullptr;
        updateUI(-1);
    }

}

void SolidWapper::updateUI(int caseid)
{
    // 刷新树。
    //GUI::MainWindow * mainWindow = dynamic_cast<GUI::MainWindow *>(FITKGLODATA->getMainWindow());
    //if (mainWindow)
    //{
    //    mainWindow->updateGeometryTree();
    //}

    // 刷新可视化窗口。
    auto operGraph = FITKOPERREPO->getOperatorT<EventOper::GraphEventOperator>("GraphPreprocess");
    if (operGraph)
    {
        operGraph->updateGraphs();
    }
}
